package it.afs.worklog.persist.hibernate;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import it.afs.worklog.Attivita;
import it.afs.worklog.Cliente;
import it.afs.worklog.Commessa;
import it.afs.worklog.Registro;
import it.afs.worklog.User;
import it.afs.worklog.persist.Dao;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;

public class HibernateDao implements Dao
{
	private final static Log log = LogFactory.getLog(HibernateDao.class);
	
	private final Session session;

	public HibernateDao(Session session)
	{
		super();
		this.session = session;
	}
	
	@Override
	public User login(String username, String password)
	{
		return (User) session.createCriteria(User.class)
			.add(Restrictions.eq("username", username))
			.add(Restrictions.eq("password", password))
			.uniqueResult();
	}
	
	@Override
	@SuppressWarnings("unchecked")
	public List<Cliente> getClienti()
	{
		return session.createQuery("from Cliente c order by c.nominativo").list();
	}
	
	@Override
	public Cliente getCliente(String id)
	{
		return (Cliente)session.load(Cliente.class, id);
	}
	
	@Override
	@SuppressWarnings("unchecked")
	public List<Commessa> getCommesse(Cliente cliente)
	{
		if(cliente == null)
			return null;
		
		return session.createQuery("from Commessa c where c.cliente=:cliente")
			.setEntity("cliente", cliente)
			.list();
	}
	
	@Override
	public Commessa getCommessa(String id)
	{
		return (Commessa)session.load(Commessa.class, id);
	}
	
	@Override
	@SuppressWarnings("unchecked")
	public List<Attivita> getAttivita(Commessa commessa)
	{
		return session.createQuery("from Attivita a where a.commessa=:commessa")
			.setEntity("commessa", commessa)
			.list();
	}
	
	@Override
	public Attivita getAttivita(String id)
	{
		return (Attivita)session.load(Attivita.class, id);
	}
	
	@Override
	public int getCountOre(Date data, User user)
	{
		return ((Long)session.createQuery("select count(*) from Registro r where r.data=:data and r.user=:user")
			.setDate("data", data)
			.setEntity("user", user)
			.iterate().next()).intValue();
	}
	
	@Override
	@SuppressWarnings("unchecked")
	public List<User> getUtenti()
	{
		return session.createQuery("from User u order by u.nome").list();
	}
	
	@Override
	public User getUser(String id)
	{
		return (User)session.load(User.class, id);
	}
	
	@Override
	public boolean existUser(String username)
	{
		return session.createQuery("from User u where u.username=:value")
			.setString("value", username)
			.list().size() == 1;
	}
	
	@Override
	public boolean set(Registro registro)
	{
		try {
			session.saveOrUpdate(registro);
			return true;
		} catch (Exception e) {
			log.trace(e);
			return false;
		}
	}
	
	@Override
	public boolean set(Cliente cliente)
	{
		try {
			session.saveOrUpdate(cliente);
			return true;
		} catch (Exception e) {
			log.trace(e);
			return false;
		}
	}
	
	@Override
	public boolean set(Commessa commessa)
	{
		try {
			session.saveOrUpdate(commessa);
			return true;
		} catch (Exception e) {
			log.trace(e);
			return false;
		}
	}
	
	@Override
	public boolean set(Attivita attivita)
	{
		try {
			session.saveOrUpdate(attivita);
			return true;
		} catch (Exception e) {
			log.trace(e);
			return false;
		}
	}
	
	@Override
	public boolean set(User user)
	{
		try {
			session.saveOrUpdate(user);
			return true;
		} catch (Exception e) {
			log.trace(e);
			return false;
		}
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public List<Registro> getLogs(Date data)
	{
		return session.createQuery("from Registro r where r.data=:data")
			.setDate("data", data)
			.list();
	}
	
	@Override
	public void deleteLogs(Date data)
	{
		session.createQuery("delete from Registro r where r.data=:data")
			.setDate("data", data)
			.executeUpdate();
	}
	
	@Override
	@SuppressWarnings("unchecked")
	public List<Registro> getReport(Date d1, Date d2, User user, Commessa commessa, String sortmode)
	{
		String order = "";
		if(sortmode.equals("1"))
			order = "r.user.nome,";
		else if(sortmode.equals("2"))
			order = "r.attivita.commessa.titolo,";
		
		String hql = "from Registro r where ", where = "";
		Map<String, Object> params = new HashMap<String, Object>();
		
		if(d1 != null)
		{
			params.put("d1", d2);
			if(d2 != null)
			{
				where += "r.data>=:d1 and r.data<=:d2";
				params.put("d2", d2);
			}
			else
				where += "r.data=:d1";
		}
		
		if(user != null)
		{
			if(where.length() > 0)
				where += " and ";
			where += "r.user=:user";
			params.put("user", user);
		}
				
		if(commessa != null)
		{
			if(where.length() > 0)
				where += " and ";
			where += "r.attivita.commessa=:commessa";
			params.put("commessa", user);
		}

		Query q = session.createQuery(hql + where + " order by " + order + "r.data");
		for(String key : params.keySet())
		{
			q.setParameter(key, params.get(key));
		}
		
		return q.list();
	}
}